package xyz.redtorch.client.strategy;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import xyz.redtorch.common.service.FastEventService;
import xyz.redtorch.common.service.FastEventService.FastEvent;
import xyz.redtorch.common.service.FastEventService.FastEventDynamicHandlerAbstract;
import xyz.redtorch.common.service.FastEventService.FastEventType;
import xyz.redtorch.pb.CoreField.AccountField;
import xyz.redtorch.pb.CoreField.ContractField;
import xyz.redtorch.pb.CoreField.NoticeField;
import xyz.redtorch.pb.CoreField.OrderField;
import xyz.redtorch.pb.CoreField.PositionField;
import xyz.redtorch.pb.CoreField.TickField;
import xyz.redtorch.pb.CoreField.TradeField;

@Service
public class StrategyEngineServiceImpl extends FastEventDynamicHandlerAbstract implements StrategyEngineService {

	private static final Logger logger = LoggerFactory.getLogger(StrategyEngineServiceImpl.class);

	private Map<String, StrategyTemplate> strategyDict = new ConcurrentHashMap<>();

	private boolean engineSwitch;

	@Autowired
	private FastEventService fastEventService;

	@Override
	public void onEvent(final FastEvent fastEvent, long sequence, boolean endOfBatch) throws Exception {

		if (!subscribedFastEventTypeSet.contains(fastEvent.getFastEventType())) {
			return;
		}

		if (FastEventType.TICK.equals(fastEvent.getFastEventType())) {
			try {
				TickField tick = (TickField) fastEvent.getObj();
				onTick(tick);
			} catch (Exception e) {
				logger.error("onTick发生异常", e);
			}
		} else if (FastEventType.TRADE.equals(fastEvent.getFastEventType())) {
			try {
				TradeField trade = (TradeField) fastEvent.getObj();
				onTrade(trade);
			} catch (Exception e) {
				logger.error("onTrade发生异常", e);
			}
		} else if (FastEventType.ORDER.equals(fastEvent.getFastEventType())) {
			try {
				OrderField order = (OrderField) fastEvent.getObj();
				onOrder(order);
			} catch (Exception e) {
				logger.error("onOrder发生异常", e);
			}
		} else if (FastEventType.CONTRACT.equals(fastEvent.getFastEventType())) {
			try {
				ContractField contract = (ContractField) fastEvent.getObj();
				onContract(contract);
			} catch (Exception e) {
				logger.error("onContract发生异常", e);
			}
		} else if (FastEventType.POSITION.equals(fastEvent.getFastEventType())) {
			try {
				PositionField position = (PositionField) fastEvent.getObj();
				onPosition(position);
			} catch (Exception e) {
				logger.error("onPosition发生异常", e);
			}
		} else if (FastEventType.ACCOUNT.equals(fastEvent.getFastEventType())) {
			try {
				AccountField account = (AccountField) fastEvent.getObj();
				onAccount(account);
			} catch (Exception e) {
				logger.error("onAccount发生异常", e);
			}
		} else if (FastEventType.LOG.equals(fastEvent.getFastEventType())) {
			// NOP
		} else if (FastEventType.NOTICE.equals(fastEvent.getFastEventType())) {
			try {
				NoticeField notice = (NoticeField) fastEvent.getObj();
				onNotice(notice);
			} catch (Exception e) {
				logger.error("onNotice发生异常", e);
			}
		} else {
			logger.warn("未能识别的事件数据类型{}", fastEvent.getEvent());
		}
	}

	@Override
	public void start() {
		if (!engineSwitch) {
			logger.info("启动异步处理线程");
			fastEventService.addHandler(this);
			subscribeFastEventType(FastEventType.ACCOUNT);
			subscribeFastEventType(FastEventType.CONTRACT);
			subscribeFastEventType(FastEventType.ORDER);
			subscribeFastEventType(FastEventType.POSITION);
			subscribeFastEventType(FastEventType.TICK);
			subscribeFastEventType(FastEventType.TRADE);
			subscribeFastEventType(FastEventType.LOG);
			subscribeFastEventType(FastEventType.NOTICE);
			engineSwitch = true;
		}
	}

	@Override
	public void addStrategy(StrategyTemplate strategy) {
		strategyDict.put(strategy.getStrategyId(), strategy);
	}

	@Override
	public void removeStrategy(String strategyId) {
		if (strategyDict.containsKey(strategyId)) {
			StrategyTemplate strategy = strategyDict.remove(strategyId);
			strategy.stopTrading(true);
		}
	}

	@Override
	public void onTick(TickField tick) {
		for (String key : strategyDict.keySet()) {
			StrategyTemplate strategy = strategyDict.get(key);
			if (strategy.getSubscribedUnifiedSymbolSet().contains(tick.getUnifiedSymbol())) {
				strategy.processTick(tick);
			}
		}
	}

	@Override
	public void onOrder(OrderField order) {
		for (String key : strategyDict.keySet()) {
			StrategyTemplate strategy = strategyDict.get(key);
			strategy.processOrder(order);
		}
	}

	@Override
	public void onTrade(TradeField trade) {
		for (String key : strategyDict.keySet()) {
			StrategyTemplate strategy = strategyDict.get(key);
			strategy.processTrade(trade);
		}
	}

	@Override
	public void onNotice(NoticeField notice) {
	}

	@Override
	public void onContract(ContractField contract) {
	}

	@Override
	public void onAccount(AccountField account) {
	}

	@Override
	public void onPosition(PositionField position) {
	}

}
